#列表的使用

#当我们有多个数据需要按照一定顺序保存时，我们可以考虑列表
#name1 = '张三'
#name2 = '李四'
#name3 = '王五'
#name4 = 'Jack'

#使用[]来表示一个列表，列表里的每一个数据我们称之为元素
#元素之间用逗号进行分割
names = ['张三','李四','王五','Jack','张飞','关羽','刘备','曹操','孙权']
print(names)

#可以用 list(可迭代对象) 将可迭代对象转换成为一个列表
names = list(('张三','李四','王五','Tony','张飞','关羽','刘备','曹操','孙权'))
print(names)

#和字符串一样，都可以使用下标来获取元素和对元素进行切片
#同时，我们还可以使用下标来修改列表里的元素，但字符串不能修改，字符串是不可变数据类型
#列表可以修改

print(names[3])
names[3] = '诸葛亮'
print(names)

print(names[3:5])#也是左闭右开区间

#列表的操作

#列表是用来保存多个数据的，是有序可变的
#操作列表，一般都包含增加数据，删除数据，修改数据以及查询数据
#增删改查

heros = ['刘备','张飞','关羽','曹操','孙权','诸葛亮']

#添加元素的方法    append insert extend
heros.append('孙策')
print(heros)#append 在列表的最后面追加一个数据

#insert(index,object)   需要两个参数  index表示下标   object表示对象，具体插入到哪个数据前面
heros.insert(4,'大乔')
print(heros)

x = ['周瑜','黄盖','司马懿']
#exitend(interanle)需要一个可迭代对象
#A.entend(B) ==> 将可迭代对象B添加到A里

heros.extend(x)

print(heros)
print(x)
#也可以用加法将列表合并

#列表的删除
heros = ['刘备','张飞','关羽','曹操','孙权','诸葛亮','Jerry']
#pop remove clear
x = heros.pop()#pop默认删除列表最后一个数据，并且返回这个数据
print(x)
print(heros)
x = heros.pop(3)#pop可以删除指定位置上的数据，也可以返回被删除的这个数据
print(x)
print(heros)

#用来删除指定的元素
heros.remove('张飞')#如果数据在列表中不存在会报错
print(heros)

#clear 用来清空一个列表
heros.clear()
print(heros)

#查询列表元素
三国 = ['魏','蜀','吴']
print(三国.index('吴'))#查询元素的位置    如果元素不存在会报错
print(三国.count('吴'))#查询出现的次数

print('魏'in 三国)

#列表的修改
#使用下标可以直接修改列表里的元素
三国[1] = 'shu'
print(三国)

#列表的遍历
#遍历：将所有数据都访问一遍，遍历针对的是可迭代对象
#while遍历    for...in遍历
水浒传 = ['宋江','晁盖','吴用','林冲','公孙胜','卢俊义','呼延灼','柴进','鲁智深','武松','李逵','阮小五','阮小七','扈三娘','时迁','白胜','孙二娘']
#for in 循环的本质就是不断调用迭代器的 next 方法查找下一个数据
for k in 水浒传:
    print(k)
    
i = 0
while i <   len(水浒传):
    print(水浒传[i])
    i += 1
    
#列表的排序和反转
nums = [9,5,7,6,8,2,1,3,4,6]
#调用列表的sort方法可以直接对列表进行排序
#sort直接对原有的列表进行排序
nums.sort()
print(nums)
#反转
nums.sort(reverse = True)
print(nums)

#内置函数sorted
#内置函数sorted不会改变原有的列表数据，而是会生成一个新的有序数据
x = sorted(nums)
print(nums)
print(x)

#reverse
numes = ['zhangsan','lisi','wangwu']
names.reverse()
print(numes)

print(numes[::-1])

#可变数据类型和不可变数据类型
num1 = [100,200,300]
num2 = num1
print('前num1=%X,num2=%X'%(id(num1),id(num2)))
num1[0] = 1
print(num1)
print('后num1=%X,num2=%X'%(id(num1),id(num2)))

'''
python里的数据都是保存在内存里的
python里的数据又分为可变类型和不可变类型
不可变类型：字符串、数字、元组
可变类型：   列表、字典、集合
不可变数据类型如果修改值，内存地址会发生变化
可变数据类型如果修改值，内存地址不会发生变化

使用内置函数id可以获取到一个变量的内存地址
'''
a=12
b=a
print('前a=%X,b=%X'%(id(a),id(b)))
a=10
print('后a=%X,b=%X'%(id(a),id(b)))

'''
p80
'''
#列表的复制
x = [100,200,300]
y = x   #x和y指向了同一个内存空间，会相互影响
x[0] = 1
print(y)
print(x)

#调用列表的copy方法可以直接对列表进行复制,这个列表和原有列表内容一样，但指向不同的内存空间
z = x.copy()
print(z)

print('%X %X %X' % (id(x),id(y),id(z)))

#除了使用列表自带的copy方法以外，还可以使用copy模块实现拷贝

import copy

a = copy.copy(x)#效果等价于x.copy()，都是一个浅拷贝



#切片就是一个浅拷贝
names1 = ['张三','李四','王五','杰克马','汤姆','露西','莉莉']
names2 = names1[::]
names1[0] = 'jerry'
print(names2)

#删除列表里的空字符串
x = ['zhangsan','lili','yanyan','','tom','','xx','']
i = 0
while i < len(x):
    if x[i] == "":
        x.remove(x[i])
        i -= 1
    i += 1
print(x)

#列表的嵌套
num = [1,2,3,[100,200,300,500],4,5]#等价于多维数组
#一个学校有三个办公室，现在有10位老师等待工位的分配，请编写程序完成随机的分配
import random

teachers = ['A','B','C','D','E','F','G','H','I','j']
rooms = [[],[],[]]

for teacher in teachers:
    room = random.choice(rooms)#choice 从列表里随机选择一个数据
    room.append(teacher)
    
print(rooms)
#for循环带下标的遍历
for i,room in enumerate(rooms):
    print('房间%d里面一共有%d个老师，分别是：' % (i,len(room)),end=' ')
    for teacher in room:
        print(teacher,end=' ')
    print()

#列表推导式
#列表推导式作用是使用简单的一个语法创建一个列表
nums = [i for i in range(10)]
print(nums)

points = [(x,y)for x in range(5,9)for y in range(10,20)]
print(points)


#写出一段代码实现分组一2个list里面的元素，比如[1,2,3,4,……,100]变成[[1,2,3],[4,5,6],……]
m = [i for i in range(1,101)]
n = [m[j:j+3]for j in range(0,100)]
print(n)

#浅拷贝
import copy
nums = [1,2,3,4,5]
nums2 = nums.copy()#浅拷贝，两个内容一模一样，但不是同一个对象
nums3 = copy,copy(nums) #和nums.copy 的功能一至，都是浅拷贝，但这个要用copy文件，需要使用import copy

#深拷贝    只能使用copy模块实现
words = ['hello','hi',[100,200,300],'yes','ok']

#word1是word的一个浅拷贝
#浅拷贝可以认为只拷贝了一层
words1 = word.copy()
words[0] = '你好'
print(word1)

words[2][0] = 1
print(words1)
#这里列表里面嵌套的列表是指向的关系，
#浅拷贝不会复制指向的内容，而是拷贝后的数据也指向这个地址，如果修改了指向的原内容，那么浅拷贝数据也会变化


#深拷贝就是完全拷贝
words = ['hello','hi',[100,200,300],'yes','ok']
words2 = copy.deepcopy(words)

#而深拷贝会将所指向的内容也拷贝一份，所以修改原内容，深拷贝的值不变